`include "axi_type_def.svh"

module uncache_2
(
    input         clk,
    input         resetn, 

    //inst sram-like 
    input         inst_req     ,
    input         inst_wr      ,
    input  [1 :0] inst_size    ,
    input  [31:0] inst_addr    ,
    input  [31:0] inst_wdata   ,
    output [31:0] inst_rdata   ,
    output        inst_addr_ok ,
    output        inst_data_ok ,
    
    //data sram-like 
    input         data_req     ,
    input         data_wr      ,
    input  [1 :0] data_size    ,
    input  [31:0] data_addr    ,
    input  [31:0] data_wdata   ,
    output [31:0] data_rdata   ,
    output        data_addr_ok ,
    output        data_data_ok ,

    output axi_req_t axi_req,
    input  axi_resp_t axi_resp
    //axi
    //ar
   
);

parameter CONST_W_CACHE = 1;
parameter CONST_R_CACHE = 2;

//addr
reg do_req;
reg do_req_or; //req is inst or data;1:data,0:inst
reg        do_wr_r;
reg [1 :0] do_size_r;
reg [31:0] do_addr_r;
reg [31:0] do_wdata_r;
wire data_back;

assign inst_addr_ok = !do_req&&!data_req;
assign data_addr_ok = !do_req;
always @(posedge clk)
begin
    do_req     <= !resetn                       ? 1'b0 : 
                  (inst_req||data_req)&&!do_req ? 1'b1 :
                  data_back                     ? 1'b0 : do_req;
    do_req_or  <= !resetn ? 1'b0 : 
                  !do_req ? data_req : do_req_or;

    do_wr_r    <= data_req&&data_addr_ok ? data_wr :
                  inst_req&&inst_addr_ok ? inst_wr : do_wr_r;
    do_size_r  <= data_req&&data_addr_ok ? data_size :
                  inst_req&&inst_addr_ok ? inst_size : do_size_r;
    do_addr_r  <= data_req&&data_addr_ok ? data_addr :
                  inst_req&&inst_addr_ok ? inst_addr : do_addr_r;
    do_wdata_r <= data_req&&data_addr_ok ? data_wdata :
                  inst_req&&inst_addr_ok ? inst_wdata :do_wdata_r;
end

//inst sram-like
assign inst_data_ok = do_req&&!do_req_or&&data_back;
assign data_data_ok = do_req&& do_req_or&&data_back;
assign inst_rdata   = axi_resp.RDATA;
assign data_rdata   = axi_resp.RDATA;

//---axi
reg addr_rcv;
reg wdata_rcv;

assign data_back = addr_rcv && ( axi_resp.RVALID && axi_req.RREADY||axi_resp.BVALID&&axi_req.BREADY);
always @(posedge clk)
begin
    addr_rcv  <= !resetn          ? 1'b0 :
                 axi_req.ARVALID&&axi_resp.ARREADY ? 1'b1 :
                 axi_req.AWVALID&&axi_resp.AWREADY ? 1'b1 :
                 data_back        ? 1'b0 : addr_rcv;
    wdata_rcv <= !resetn        ? 1'b0 :
                 axi_req.WVALID&&axi_resp.WREADY ? 1'b1 :
                 data_back      ? 1'b0 : wdata_rcv;
end
//ar
assign axi_req.ARID    = CONST_R_CACHE;
assign axi_req.ARADDR  = do_addr_r;
assign axi_req.ARLEN   = 4'd0;
assign axi_req.ARSIZE  = do_size_r;
assign axi_req.ARLOCK  = 2'd0;
assign axi_req.ARCACHE = 4'd0;
assign axi_req.ARPROT  = 3'd0;
assign axi_req.ARVALID = do_req&&!do_wr_r&&!addr_rcv;
//r
assign axi_req.RREADY  = 1'b1;

//aw
assign axi_req.AWID    = CONST_W_CACHE;
assign axi_req.AWADDR  = do_addr_r;
assign axi_req.AWLEN   = 4'd0;
assign axi_req.AWSIZE  = do_size_r;
assign axi_req.AWBURST = 2'd0;
assign axi_req.AWLOCK  = 2'd0;
assign axi_req.AWCACHE = 4'd0;
assign axi_req.AWPROT  = 3'd0;
assign axi_req.AWVALID = do_req&&do_wr_r&&!addr_rcv;
//w
assign axi_req.WID    = CONST_W_CACHE;
assign axi_req.WDATA  = do_wdata_r;
assign axi_req.WSTRB  = do_size_r==2'd0 ? 4'b0001<<do_addr_r[1:0] :
                do_size_r==2'd1 ? 4'b0011<<do_addr_r[1:0] : 4'b1111;
assign axi_req.WLAST  = 1'd1;
assign axi_req.WVALID = do_req&&do_wr_r&&!wdata_rcv;
//b
assign axi_req.BREADY  = 1'b1;

endmodule

